/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author carlcarl
 */
import java.applet.Applet;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
import java.io.*;
import java.net.*;


public class Go extends Applet 
{
    private static final int GO_X_BASE = 23;
    private static final int GO_Y_BASE = 26;
    private static final int CLICK_X_BASE = GO_X_BASE + 11;
    private static final int CLICK_Y_BASE = GO_Y_BASE + 11;
    private static final int GO_X_PLUS = 22;
    private static final int GO_Y_PLUS = 22;
    public static final int DESKWIDTH = 515;
    public static final int DESKHEIGHT = 515;
    
    private JPanel toolPanel;
    private JPanel playerPanel; //place player's name
    private MainPanel mainPanel;
    
    private JButton next, nextTen, back, backTen, first, last; // move
    private JButton autoNext;
    private JLabel wPlayer, bPlayer; //name
    private JLabel result;
    private JLabel wAdd; //white's additional point
    
    private Image desk;
    private Image black;
    private Image white;
    private Image blackNow;
    private Image whiteNow;
    private BufferedImage all;
    private ImageIcon oneForward;
    private ImageIcon oneBack;
    private ImageIcon fastForward;
    private ImageIcon fastBack;
    private ImageIcon allBack;
    private ImageIcon allForward;
    private ImageIcon auto;
    private ImageIcon stop;
    
    private URL url;
    private InputStream in;
    private BufferedReader reader;
    private MapData mapData;
    private MapData vMapData;

    private MouseAction mouseAction;
    
    private javax.swing.Timer timer;
    /**
     * Initialization method that will be called after the applet is loaded
     * into the browser.
     */
    @Override
    public void init() 
    {
        try
        {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        }
        catch (ClassNotFoundException ex)
        {
            Logger.getLogger(Go.class.getName()).log(Level.SEVERE, null, ex);
        }
        catch (InstantiationException ex)
        {
            Logger.getLogger(Go.class.getName()).log(Level.SEVERE, null, ex);
        }
        catch (IllegalAccessException ex)
        {
            Logger.getLogger(Go.class.getName()).log(Level.SEVERE, null, ex);
        }
        catch (UnsupportedLookAndFeelException ex)
        {
            Logger.getLogger(Go.class.getName()).log(Level.SEVERE, null, ex);
        }
        this.setLayout(new BorderLayout()); 
        try
        {
            desk = new ImageIcon(new java.net.URL
                (this.getCodeBase(),"images/desk.jpg")).getImage();
            black = new ImageIcon(new java.net.URL
                (this.getCodeBase(),"images/black.png")).getImage();
            white = new ImageIcon(new java.net.URL
                (this.getCodeBase(),"images/white.png")).getImage();
            blackNow = new ImageIcon(new java.net.URL
                (this.getCodeBase(),"images/blacknow.png")).getImage();
            whiteNow = new ImageIcon(new java.net.URL
                (this.getCodeBase(),"images/whitenow.png")).getImage();
            oneForward = new ImageIcon(new java.net.URL
                    (getCodeBase(),"images/oneforward.gif"));
            oneBack = new ImageIcon(new java.net.URL
                    (getCodeBase(),"images/oneback.gif"));
            fastForward = new ImageIcon(new java.net.URL
                    (getCodeBase(),"images/fastforward.gif"));
            fastBack = new ImageIcon(new java.net.URL
                    (getCodeBase(),"images/fastback.gif"));
            allForward = new ImageIcon(new java.net.URL
                    (getCodeBase(),"images/allforward.gif"));
            allBack = new ImageIcon(new java.net.URL
                    (getCodeBase(),"images/allback.gif"));
            auto = new ImageIcon(new java.net.URL
                    (getCodeBase(),"images/animate.gif"));
            stop = new ImageIcon(new java.net.URL
                    (getCodeBase(),"images/close.gif"));
        }
        catch(Exception ex)
        {
            JOptionPane.showMessageDialog(this, "圖片讀取錯誤");
        }

        mouseAction = new MouseAction();
        this.addMouseListener(mouseAction);
        
        next = new JButton();
        next.setActionCommand(">");
        next.setPreferredSize(new Dimension(60, 30));
        next.setIcon(oneForward);
        next.addActionListener(new ButtonAction());
        next.setToolTipText("下一手");
        
        nextTen = new JButton();
        nextTen.setActionCommand(">>");
        nextTen.setPreferredSize(new Dimension(60, 30));
        nextTen.setIcon(fastForward);
        nextTen.addActionListener(new ButtonAction());
        nextTen.setToolTipText("下十手");
        
        back = new JButton();
        back.setActionCommand("<");
        back.setPreferredSize(new Dimension(60, 30));
        back.setIcon(oneBack);
        back.addActionListener(new ButtonAction());
        back.setToolTipText("上一手");
        
        backTen = new JButton();
        backTen.setActionCommand("<<");
        backTen.setPreferredSize(new Dimension(60, 30));
        backTen.setIcon(fastBack);
        backTen.addActionListener(new ButtonAction());
        backTen.setToolTipText("上十手");
        
        first = new JButton();
        first.setActionCommand("|<");
        first.setPreferredSize(new Dimension(60, 30));
        first.setIcon(allBack);
        first.addActionListener(new ButtonAction());
        first.setToolTipText("開始");
        
        last = new JButton();
        last.setActionCommand(">|");
        last.setPreferredSize(new Dimension(60, 30));
        last.setIcon(allForward);
        last.addActionListener(new ButtonAction());
        last.setToolTipText("結束");
        
        autoNext = new JButton();
        autoNext.setActionCommand("auto");
        autoNext.setPreferredSize(new Dimension(60, 30));
        autoNext.setIcon(auto);
        autoNext.addActionListener(new ButtonAction());
        autoNext.setToolTipText("自動撥放");
        
        toolPanel = new JPanel();
        toolPanel.setPreferredSize(new Dimension(70, 400));
        toolPanel.add(autoNext);
        toolPanel.add(next);
        toolPanel.add(nextTen);
        toolPanel.add(last);
        toolPanel.add(back);
        toolPanel.add(backTen);
        toolPanel.add(first);

        /*toolPanel.setBorder(BorderFactory.createEtchedBorder(Color.black,
                Color.gray));*/
        this.add(toolPanel, BorderLayout.EAST);
        
        playerPanel = new JPanel();
        playerPanel.setLayout(new GridLayout(2, 2));
        Font font = new Font(null, Font.BOLD, 24);
        //playerPanel.setFont(font);
        //playerPanel.setBackground(Color.GREEN);////////////////////
        wPlayer = new JLabel("白方：");
        wPlayer.setFont(font);
        bPlayer = new JLabel("黑方：");
        bPlayer.setFont(font);
        result = new JLabel("結果：");
        result.setFont(font);
        wAdd = new JLabel("讓子：");
        wAdd.setFont(font);
        playerPanel.add(wPlayer);
        playerPanel.add(bPlayer);
        playerPanel.add(result);
        playerPanel.add(wAdd);
        /*playerPanel.setBorder(BorderFactory.createEtchedBorder(Color.black,
                Color.gray));*/
        this.add(playerPanel, BorderLayout.SOUTH);
        
        mapData = new MapData(this);
        vMapData = new MapData(this);
        mainPanel = new MainPanel();
        
        this.add(mainPanel, BorderLayout.CENTER);
        
        try
        {
            String goFile = this.getParameter("goFile");
            url = new URL(this.getCodeBase(), goFile);
            in = url.openStream();
        }
        catch(IOException ex)
        {
              JOptionPane.showMessageDialog(this, "FileReader Error");
        }
        reader = new BufferedReader(new InputStreamReader(in));
        readFile();

    }
    
    
    public void readFile()
    {
        String line = null;
        String target = null;
        try
        {
            //input = new Scanner(connect.getInputStream());
            while((line = reader.readLine()) != null)
            {
                int index = -1;
                for(int i = 0; i < line.length(); i++)
                {
                    if((line.charAt(i) == ';') && ((line.charAt(i + 1) == 'W')
                            || (line.charAt(i + 1) == 'B')) 
                            && (line.charAt(i + 3) != ']'))//if any go step
                    {
                        int x = line.charAt(i + 3) - 'a' + 1;
                        int y = line.charAt(i + 4) - 'a' + 1;
                        GoData goData = new GoData(line.charAt(i + 1),
                                x, y);
                        mapData.produceMap(goData);
                    }
                }
                if((index = line.indexOf("PB")) != -1)// black's name
                {
                    for(int i = index + 3; i < line.length(); i++)
                    {
                        if(line.charAt(i) == ']')
                        {
                            target = line.substring(index + 3, i);
                            bPlayer.setText(bPlayer.getText() + target);
                            break;
                        }
                    }
                }
                if((index = line.indexOf("BR")) != -1)// black's rank
                {
                    for(int i = index + 3; i < line.length(); i++)
                    {
                        if(line.charAt(i) == ']')
                        {
                            target = line.substring(index + 3, i);
                            bPlayer.setText(bPlayer.getText() + " " + target);
                            break;
                        }
                    }
                }
                if((index = line.indexOf("PW")) != -1)// white's name
                {
                    for(int i = index + 3; i < line.length(); i++)
                    {
                        if(line.charAt(i) == ']')
                        {
                            target = line.substring(index + 3, i);
                            wPlayer.setText(wPlayer.getText() + target);
                            break;
                        }
                    }
                }
                if((index = line.indexOf("WR")) != -1)//white's rank
                {
                    for(int i = index + 3; i < line.length(); i++)
                    {
                        if(line.charAt(i) == ']')
                        {
                            target = line.substring(index + 3, i);
                            wPlayer.setText(wPlayer.getText() + " " + target);
                            break;
                        }
                    }
                }
                if((index = line.indexOf("RE")) != -1)//result
                {
                    for(int i = index + 3; i < line.length(); i++)
                    {
                        if(line.charAt(i) == ']')
                        {
                            target = line.substring(index + 3, i);
                            result.setText(result.getText() + target);
                            break;
                        }
                    }
                }
                if((index = line.indexOf("KM")) != -1)//w's additional point
                {
                    for(int i = index + 3; i < line.length(); i++)
                    {
                        if(line.charAt(i) == ']')
                        {
                            target = line.substring(index + 3, i);
                            wAdd.setText(wAdd.getText() + target);
                            break;
                        }
                    }
                }
            }
        }
        catch(IOException ex)
        {
            JOptionPane.showMessageDialog(this, ex.getMessage());
        }
        buttonEnableBack(false);
        
    }

    // 棋盤
    class MainPanel extends JPanel
    {
        private byte[][] map, map2;
        private Graphics g2;

        MainPanel()
        {
            //super();
        }
        @Override
        public void paint(Graphics g)
        {
            this.paintComponent(g);
        }
        @Override
        protected void paintComponent(Graphics g)
        { 

            all = (BufferedImage)createImage(DESKWIDTH, DESKHEIGHT);
            g2 = all.createGraphics();
            g2.drawImage(desk, 0, 0, null);

            int nowStep = mapData.getNowStep();
            if(vMapData.getFinalStep() == 0)
            {

                map = mapData.getGoMap(nowStep);

                for(int i = 1; i <= 19; i++)
                {
                    for(int j = 1; j <= 19; j++)
                    {
                        if((map[i][j] == MapData.B))
                        {
                            g2.drawImage(black, GO_X_BASE
                            + ((i - 1) * GO_X_PLUS)
                            ,GO_Y_BASE
                            + (j - 1) * GO_Y_PLUS, null);
                        }
                        else if(map[i][j] == MapData.W)
                        {
                            g2.drawImage(white, GO_X_BASE
                            + ((i - 1) * GO_X_PLUS)
                            ,GO_Y_BASE
                            + (j - 1) * GO_Y_PLUS, null);
                        }
                    }
                }
                //目前這一步的標示
                if((mapData.getStepPositionColor(nowStep) == 'B') &&
                    (mapData.getNowStep() != 0))
                {
                    g2.drawImage(blackNow, GO_X_BASE
                            + ((mapData.getStepPositionX(nowStep) - 1) * GO_X_PLUS)
                            ,GO_Y_BASE
                            + (mapData.getStepPositionY(nowStep) - 1) * GO_Y_PLUS
                            , null);
                }
                else if((mapData.getStepPositionColor(nowStep) == 'W') &&
                        (mapData.getNowStep() != 0))
                {
                    g2.drawImage(whiteNow, GO_X_BASE
                            + ((mapData.getStepPositionX(nowStep) - 1) * GO_X_PLUS)
                            ,GO_Y_BASE
                            + (mapData.getStepPositionY(nowStep) - 1) * GO_Y_PLUS
                            , null);
                }
            }
            else
            {
                int finalStep = vMapData.getFinalStep();

                map2 = vMapData.getGoMap(finalStep);
                for(int i = 1; i <= 19; i++)
                {
                    for(int j = 1; j <= 19; j++)
                    {
                        if((map2[i][j] == MapData.B))
                        {
                            g2.drawImage(black, GO_X_BASE
                            + ((i - 1) * GO_X_PLUS)
                            ,GO_Y_BASE
                            + (j - 1) * GO_Y_PLUS, null);
                        }
                        else if(map2[i][j] == MapData.W)
                        {
                            g2.drawImage(white, GO_X_BASE
                            + ((i - 1) * GO_X_PLUS)
                            ,GO_Y_BASE
                            + (j - 1) * GO_Y_PLUS, null);
                        }
                    }
                }
                if(vMapData.getStepPositionColor(finalStep) == 'B')
                {
                    g2.drawImage(blackNow, GO_X_BASE
                            + ((vMapData.getStepPositionX(finalStep) - 1) * GO_X_PLUS)
                            ,GO_Y_BASE
                            + (vMapData.getStepPositionY(finalStep) - 1) * GO_Y_PLUS
                            , null);
                }
                else if(vMapData.getStepPositionColor(finalStep) == 'W')
                {
                    g2.drawImage(whiteNow, GO_X_BASE
                            + ((vMapData.getStepPositionX(finalStep) - 1) * GO_X_PLUS)
                            ,GO_Y_BASE
                            + (vMapData.getStepPositionY(finalStep) - 1) * GO_Y_PLUS
                            , null);
                }
            }
            
            g.drawImage(all, 0, 0, null);      
        }
    }

    class MouseAction extends MouseAdapter
    {
        @Override
        public void mousePressed(MouseEvent e)
        {
            //JOptionPane.showMessageDialog(null, "alert", "alert", JOptionPane.ERROR_MESSAGE);
            int x = e.getX() - CLICK_X_BASE;
            int y = e.getY() - CLICK_Y_BASE;
            int xCheck = x % GO_X_PLUS;
            int yCheck = y % GO_Y_PLUS;

            //看點擊的地方比較接近哪條線
            if(xCheck < (GO_X_PLUS / 3)) x = x / GO_X_PLUS + 1;
            else if(xCheck > (2 * GO_X_PLUS / 3)) x = x / GO_X_PLUS + 2;
            else return;
            
            if(yCheck < (GO_Y_PLUS / 3)) y = y / GO_Y_PLUS + 1;
            else if(yCheck > (2 * GO_Y_PLUS / 3)) y = y / GO_Y_PLUS + 2;
            else return;

            if(x > 19 || x < 1 || y > 19 | y < 1)
                return;

            char c = 'W';
            int nowStep = mapData.getNowStep();
            int finalStep = vMapData.getFinalStep();
            if(vMapData.getFinalStep() == 0) //第一次點擊
            {
                if(mapData.getNowStep() != 0) //棋譜已經走過幾步了
                {
                    if(mapData.getGoMap(nowStep)[x][y] != MapData.NULL) //判斷點擊的那一步是不是已經被走過了
                        return;
                    c = mapData.getStepPositionColor(nowStep) == 'W' ? 'B' : 'W';
                }
                else
                {
                    c = 'B';
                    buttonEnableBack(true);
                }
                vMapData.setMap(finalStep, mapData.getGoMap(nowStep));
            }
            else
            {
                if(vMapData.getGoMap(finalStep)[x][y] != MapData.NULL) //判斷點擊的那一步是不是已經被走過了
                    return;
                c = vMapData.getStepPositionColor(finalStep) == 'W' ? 'B' : 'W';
            }

            GoData goData = new GoData(c, x, y);
            vMapData.produceMap(goData);

            if(vMapData.getFinalStep() == 1) // 只有在點擊的第一步才把下步的功能關掉
            {
                buttonEnableForward(false);
            }

            mainPanel.repaint();
        }
    }

    class ButtonAction implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            if(e.getActionCommand().equals(">"))
            {
                if((mapData.getNowStep() + 1) <= mapData.getFinalStep())
                {
                    if(mapData.getNowStep() == 0)
                    {
                        buttonEnableBack(true);
                    }
                    mapData.setNowStep(mapData.getNowStep() + 1);
                    if(mapData.getNowStep() == mapData.getFinalStep())
                    {
                        buttonEnableForward(false);
                    }
                    mainPanel.repaint();
                }
                else if(timer != null)
                {
                    disableAuto(true);
                }
            }
            else if(e.getActionCommand().equals("<"))
            {
                if(vMapData.getFinalStep() != 0)
                {
                    vMapData.deleteLastStepData();

                    if(vMapData.getFinalStep() == 0)
                    {
                        buttonEnableForward(true);
                    }

                    mainPanel.repaint();
                }
                else if((mapData.getNowStep() - 1) >= 0)
                {
                    if(mapData.getNowStep() == mapData.getFinalStep())
                    {
                        buttonEnableForward(true);
                    }
                    mapData.setNowStep(mapData.getNowStep() - 1);
                    if(mapData.getNowStep() == 0)
                    {
                        buttonEnableBack(false);
                    }
                    mainPanel.repaint();
                }
            }
            else if(e.getActionCommand().equals(">>"))
            {
                if((mapData.getNowStep() + 10) < mapData.getFinalStep())
                {
                    if(mapData.getNowStep() == 0)
                    {
                        buttonEnableBack(true);
                    }
                    mapData.setNowStep(mapData.getNowStep() + 10);
                    mainPanel.repaint();
                }
                else if(mapData.getNowStep() != mapData.getFinalStep())
                {
                    mapData.setNowStep(mapData.getFinalStep());
                    buttonEnableForward(false);
                    mainPanel.repaint();
                }
            }
            else if(e.getActionCommand().equals("<<"))
            {
                int stepSub = 10;
                while(vMapData.getFinalStep() != 0)
                {
                    vMapData.deleteLastStepData();
                    stepSub--;
                }
                buttonEnableForward(true);
                if((mapData.getNowStep() - stepSub) >= 0)
                {
                    if(mapData.getNowStep() == mapData.getFinalStep())
                    {
                        buttonEnableForward(true);
                    }
                    mapData.setNowStep(mapData.getNowStep() - stepSub);
                    mainPanel.repaint();
                }
                else if(mapData.getNowStep() != 0)
                {
                    mapData.setNowStep(0);
                    buttonEnableBack(false);
                    mainPanel.repaint();
                }
            }
            else if(e.getActionCommand().equals("|<"))
            {
                while(vMapData.getFinalStep() != 0)
                {
                    vMapData.deleteLastStepData();
                }
                buttonEnableForward(true);
                if(mapData.getNowStep() != 0)
                {
                    if(mapData.getNowStep() == mapData.getFinalStep())
                    {
                        buttonEnableForward(true);
                    }
                    mapData.setNowStep(0);                  
                    buttonEnableBack(false);
                }
                mainPanel.repaint();
            }
            else if(e.getActionCommand().equals(">|"))
            {
                if(mapData.getNowStep() != mapData.getFinalStep())
                {
                    if(mapData.getNowStep() == 0)
                    {
                        buttonEnableBack(true);
                    }
                    mapData.setNowStep(mapData.getFinalStep());
                    mainPanel.repaint();
                    buttonEnableForward(false);
                }

            }
            else if(e.getActionCommand().equals("auto"))
            {
                if((timer == null) || (!timer.isRunning()))
                {
                    timer = new javax.swing.Timer(1000, this);
                    timer.setActionCommand(">");
                    disableAuto(false);
                }
                else if(timer.isRunning())
                {
                    disableAuto(true);
                }
            }
        }
    }

   private void  disableAuto(boolean enable)
   {
       if(enable == true)
       {
           timer.stop();
           autoNext.setIcon(auto);
           autoNext.setToolTipText("自動撥放");
           this.addMouseListener(mouseAction);
       }
       else
       {
           timer.start();
           autoNext.setIcon(stop);
           autoNext.setToolTipText("停止");
           this.removeMouseListener(mouseAction);
       }
       next.setEnabled(enable);
       nextTen.setEnabled(enable); 
       back.setEnabled(enable);
       backTen.setEnabled(enable);
       first.setEnabled(enable);
       last.setEnabled(enable);
   }

   void buttonEnableForward(boolean enable)
   {
       next.setEnabled(enable);
       nextTen.setEnabled(enable);
       last.setEnabled(enable);
       autoNext.setEnabled(enable);
   }

   void buttonEnableBack(boolean enable)
   {
       back.setEnabled(enable);
       backTen.setEnabled(enable);
       first.setEnabled(enable);
   }
    // TODO overwrite start(), stop() and destroy() methods
}
